# Copyright 2009-present MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

include(FetchCatch2)

if(NOT BUILD_TESTING)
    set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL TRUE)
endif()

if(BSONCXX_BUILD_SHARED)
    bsoncxx_add_library(bsoncxx_testing "bsoncxx-testing" SHARED)
else()
    bsoncxx_add_library(bsoncxx_testing "bsoncxx-testing" STATIC)
endif()

target_compile_definitions(bsoncxx_testing PUBLIC BSONCXX_TESTING)

set(bsoncxx_test_sources_private
    private/make_unique.test.cpp
    private/bson_version.cpp
)

set(bsoncxx_test_sources_v_noabi
    v_noabi/array.cpp
    v_noabi/bson_b_date.cpp
    v_noabi/bson_builder.cpp
    v_noabi/bson_get_values.cpp
    v_noabi/bson_serialization.cpp
    v_noabi/bson_types.cpp
    v_noabi/bson_util_itoa.cpp
    v_noabi/bson_validate.cpp
    v_noabi/bson_value.cpp
    v_noabi/json.cpp
    v_noabi/oid.cpp
    v_noabi/vector.cpp
    v_noabi/view_or_value.cpp
)

set(bsoncxx_test_sources_v1
    v1/array/value.cpp
    v1/array/view.cpp
    v1/decimal128.cpp
    v1/document/value.cpp
    v1/document/view.cpp
    v1/element/view.cpp
    v1/exception.cpp
    v1/oid.cpp
    v1/stdx/optional.test.cpp
    v1/stdx/string_view.test.cpp
    v1/stdx/type_traits.test.cpp
    v1/types/id.cpp
    v1/types/value.cpp
    v1/types/view.cpp
)

set(bsoncxx_test_sources
    ${bsoncxx_test_sources_private}
    ${bsoncxx_test_sources_v_noabi}
    ${bsoncxx_test_sources_v1}
    catch.cpp
    exception_guard.cpp
)

file(GLOB_RECURSE bsoncxx_test_headers
    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    CONFIGURE_DEPENDS
    "*.hh"
)

add_executable(test_bson
    ${bsoncxx_test_sources}
)

# Common target properties for test executables.
add_library(bsoncxx_test_properties INTERFACE)

target_link_libraries(bsoncxx_test_properties INTERFACE Catch2::Catch2)
target_compile_features(bsoncxx_test_properties INTERFACE cxx_std_14)

target_link_libraries(bsoncxx_test_properties INTERFACE bsoncxx_testing ${bson_target})
target_include_directories(bsoncxx_test_properties INTERFACE
    # Allow `#include <bsoncxx/test/...>`.
    ${CMAKE_CURRENT_SOURCE_DIR}/../..
)
# Use `__vectorcall` by default with MSVC to catch missing `__cdecl`.
target_compile_options(bsoncxx_test_properties INTERFACE "$<$<CXX_COMPILER_ID:MSVC>:/Gv>")
add_library(bsoncxx::test_properties ALIAS bsoncxx_test_properties)

# Avoid redundant recompilation of catch/main.cpp.
add_library(bsoncxx_test_properties_with_main INTERFACE)
target_link_libraries(bsoncxx_test_properties_with_main INTERFACE bsoncxx::test_properties)
target_sources(bsoncxx_test_properties INTERFACE catch.cpp)
add_library(bsoncxx::test_properties_with_main ALIAS bsoncxx_test_properties_with_main)

target_link_libraries (test_bson PRIVATE bsoncxx::test_properties_with_main)

add_test(NAME bson COMMAND test_bson --reporter compact --allow-running-no-tests)

# Generate test to ensure macro guards behave properly.
if(ENABLE_MACRO_GUARD_TESTS)
    include(MacroGuardTest)

    add_macro_guard_test(
        PROJECT_NAME bsoncxx
        PROJECT_TEST_PROPERTIES_TARGET bsoncxx::test_properties
        GUARDED_MACROS
            # bsoncxx/v1/config/config.hpp (generated by CMake)
            BSONCXX_POLY_USE_IMPLS
            BSONCXX_POLY_USE_STD

            # bsoncxx/v1/config/export.hpp (generated by CMake)
            BSONCXX_ABI_CDECL
            BSONCXX_ABI_EXPORT
            BSONCXX_ABI_EXPORT_CDECL
            BSONCXX_ABI_NO_EXPORT
            BSONCXX_DEPRECATED

            # bsoncxx/v1/config/version.hpp (generated by CMake)
            BSONCXX_VERSION_STRING
            BSONCXX_VERSION_EXTRA
            BSONCXX_VERSION_MAJOR
            BSONCXX_VERSION_MINOR
            BSONCXX_VERSION_PATCH

            # bsoncxx/v1/detail/macros.hpp
            BSONCXX_PRIVATE_CONCAT
            BSONCXX_PRIVATE_CONCAT_IMPL
            BSONCXX_PRIVATE_CONSTEXPR_CXX14
            BSONCXX_PRIVATE_FORCE_SEMICOLON
            BSONCXX_PRIVATE_FWD
            BSONCXX_PRIVATE_IF_CLANG
            BSONCXX_PRIVATE_IF_GCC
            BSONCXX_PRIVATE_IF_GNU_LIKE
            BSONCXX_PRIVATE_IF_MSVC
            BSONCXX_PRIVATE_PRAGMA
            BSONCXX_PRIVATE_PRAGMA_IMPL
            BSONCXX_PRIVATE_RETURNS
            BSONCXX_PRIVATE_STRINGIFY
            BSONCXX_PRIVATE_STRINGIFY_IMPL
            BSONCXX_PRIVATE_UNREACHABLE
            BSONCXX_PRIVATE_WARNINGS_DISABLE
            BSONCXX_PRIVATE_WARNINGS_DISABLE_IMPL_FOR_Clang
            BSONCXX_PRIVATE_WARNINGS_DISABLE_IMPL_FOR_GCC
            BSONCXX_PRIVATE_WARNINGS_DISABLE_IMPL_FOR_GNU
            BSONCXX_PRIVATE_WARNINGS_DISABLE_IMPL_FOR_MSVC
            BSONCXX_PRIVATE_WARNINGS_POP
            BSONCXX_PRIVATE_WARNINGS_PUSH
            Clang
            GCC
            GNU
            MSVC

            # bsoncxx/v1/detail/prelude.hpp
            BSONCXX_PRIVATE_V1_INSIDE_MACRO_GUARD_SCOPE

        INCLUDE_PATTERNS
            "include/*.hpp" # Public headers.
        EXCLUDE_REGEXES
            "include/bsoncxx/docs/.*\.hpp" # Doc header.
            "include/.*/(prelude|postlude)\.hpp" # Macro guard headers.
            "include/bsoncxx/v1/detail/macros\.hpp" # v1 private macros.
            "include/bsoncxx/v_noabi/bsoncxx/config/.*\.hpp" # v_noabi include-via-prelude headers.
            "include/bsoncxx/v_noabi/bsoncxx/enums/.*\.hpp" # v_noabi X-macro headers.
    )
endif()

set_dist_list(src_bsoncxx_test_DIST
    CMakeLists.txt
    ${bsoncxx_test_sources}
    ${bsoncxx_test_headers}
    test_macro_guards.cpp.in
)
